// m.cpp
// implement of class CM
//

#include "m.h"
#include "msock.h"
#include "global.h"
#include "mprotocol.h"
#include "mydb.h"
#include "user.h"

int CM::run()
{
    _pBuf = NULL;

    CMyDb db;
    db.Init();

    m_pUser = new CUser;
    
    CMSocket net;
    CMLog::Plog("sizeof(int):%d, sizeof(long):%d", sizeof(int), sizeof(long));
    net.start(this, "172.16.10.17", "18888");

    delete (CUser*)m_pUser;

    return 0;
}

#define MAX_TEXT    64*1024
int CM::Do(int fd)
{
    CMLog log("CM::Do");
    // receive data and response.
    if (_pBuf == NULL)
    {
        _pBuf = new char[MAX_TEXT];
    }

    bzero(_pBuf, sizeof(char)*MAX_TEXT);
    char *p = _pBuf;

    // read out the header
    int length = 0;
    read(fd, &length, sizeof(int));
    unsigned char type = 0;
    read(fd, &type, 1);
    CMLog::Plog("type: %d, length: %d", type, ntohl(length));
    if (length > MAX_TEXT)
    {
        delete[] _pBuf;
        _pBuf = new char[MAX_TEXT+length];
        bzero(_pBuf, sizeof(char)*(MAX_TEXT+length));
        p = _pBuf;
    }
    read(fd, p, length);
    switch (type)
    {
        case NPT_REGISTRY:
            Registry(fd, p);
            break;
        case NPT_LOGIN:
            Login(fd, p);
            break;
        case NPT_LOGOUT:
            Logout(fd, p);
            break;
        case NPT_MESSAGE:
            Message(fd, p);
            break;
        case NPT_TERM_SERVER:
            return Cmd(fd, p);
            break;
        default:
            break;
    }
    return 0;
}

void CM::Registry(int fd, char *p)
{
    CByteStream bs((unsigned char*)p);
    int len = 0;
    bs>>len;
    char *name = new char[len+1];
    bzero(name, len+1);
    bs.Read(name, len);

    bs>>len;
    char *pwd = new char[len+1];
    bzero(pwd, len+1);
    bs.Read(pwd, len);
    CMyDb db;
    char ip[20] = {"0.0.0.0"};
    int port = 0;
    CMTools::GetPeerIpPort(fd, ip, port);
    CMTools::GetLocalIpPort(fd, ip, port);
    int ret = db.Add(fd, ip, port, name, pwd);
    // response
    {
    char res[256] = {0};
    CByteStream bs((unsigned char*)res);
    unsigned char type = RNPT_REGISTRY;
    int blen = sizeof(ret);
    bs<<blen;
    bs<<type;
    bs<<ret;
    write(fd, bs.GetData(), bs.Tell());
    }

    CMLog::Plog("registry: name: %s, pwd: %s, uid: %d", name, pwd, db.GetUserId(name));
    delete[] name;
    delete[] pwd;
}

void CM::Login(int fd, char *p)
{
    CByteStream bs((unsigned char*)p);
    int len = 0;
    bs>>len;
    char *name = new char[len+1];
    bzero(name, len+1);
    bs.Read(name, len);

    bs>>len;
    char *pwd = new char[len+1];
    bzero(pwd, len+1);
    bs.Read(pwd, len);

    CMyDb db;
    int uid = db.CheckUser(name, pwd);
    if (uid > 0)
    {
        CUser *pUser = (CUser*)m_pUser;
        if (pUser)pUser->AddUser(uid, fd);
    }
    {
        char buf[256] = {0};
        CByteStream bs((unsigned char*)buf);
        int blen;
        blen = sizeof(int);
        unsigned char type = RNPT_LOGIN;
        bs<<blen;
        bs<<type;
        bs<<uid;
        
        write(fd, bs.GetData(), bs.Tell());
        CMLog::Plog("response: blen:%d, type:%d, data:%d", blen, type, uid);
    }

    CMLog::Plog("login: name: %s, pwd: %s, uid: %d", name, pwd, uid);
    delete[] name;
    delete[] pwd;
}

void CM::Logout(int fd, char *p)
{
    CByteStream bs((unsigned char*)p);
    int uid;
    bs>>uid;
    CUser* pUser = (CUser*)m_pUser;
    if (pUser)
        pUser->DeleteUser(uid);

    {
        char buf[20] = {0};
        CByteStream bs((unsigned char*)buf);
        unsigned char type = RNPT_LOGOUT;
        int blen = 1;
        bs<<blen;
        bs<<type;
        bs<<(unsigned char)1;
        write(fd, bs.GetData(), bs.Tell()); 
        CMLog::Plog("response logout: type:%d, uid:%d, %d", type, uid, bs.Tell());
    }
}

int CM::Cmd(int fd, char *p)
{
    CMLog::Plog("received close the server command");
    CByteStream bs((unsigned char*)p);
    int cmd = 0;
    bs>>cmd;
    CMLog::Plog("check terminal cmd: %d", cmd);

    close(fd);
    return 88;
}

void CM::Message(int fd, char *p)
{
    CByteStream bs((unsigned char*)p);
    int toUid = 0;
    int fromUid = 0;
    int msglen = 0;

    int tmp;
    bs>>tmp;
    bs>>tmp;
    bs>>toUid;

    CUser *pUser = (CUser*)m_pUser;
    int tofd = 0;
    if (pUser)
        tofd = pUser->SearchUser(toUid);
    if (tofd > 0)
    ;//    write(tofd, p, (length-sizeof(type)-sizeof(length)));

    bs>>fromUid;
    bs>>msglen;
    CMLog::Plog("[%d] to [%d], fd=%d, msglen: %d", fromUid, toUid, tofd, msglen);
    msglen = 5;
    char *msg = new char[msglen+1];
    bzero(msg, msglen+1);
    bs.Read(msg, msglen);
    CMLog::Plog("recevie msg from %d to %d : %s", fromUid, toUid, msg);

    delete[] msg;
}

